package com.ruoyi.lvlian.util;

import java.lang.reflect.Method;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelReader;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.enums.CellDataTypeEnum;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.excel.metadata.Cell;
import com.alibaba.excel.metadata.data.ReadCellData;
import com.alibaba.excel.read.metadata.ReadSheet;
import com.ruoyi.lvlian.domain.InvoiceDetails;
import io.swagger.annotations.ApiModelProperty;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Excel解析工具类
 */
public class ExcelUtil {

    private ExcelUtil() {
    }

    /**
     * 从字节数组中读取 Excel 数据
     *
     * @param fileAsBytes Excel 文件的字节数组
     * @param clazz       目标对象的类
     * @param <T>         对象类型
     * @param sheetName   工作表表名
     * @param rowNum      解析开始行数
     * @return Excel 数据集合
     * @throws IOException IO 异常
     */
    public static <T> List<T> readExcel(byte[] fileAsBytes, Class<T> clazz, String sheetName, int rowNum) {
        // 将字节数组转换为 ByteArrayInputStream
        ByteArrayInputStream inputStream = new ByteArrayInputStream(fileAsBytes);
        // 创建 ExcelReader 对象
        ExcelReader excelReader = EasyExcel.read(inputStream).build();
        try {
            // 创建 Excel 数据集合
            List<T> dataList = new ArrayList<>();
            // 读取 Excel 数据
            ReadSheet readSheet = EasyExcel.readSheet(sheetName).head(clazz).headRowNumber(rowNum).registerReadListener(
                    new AnalysisEventListener<T>() {
                        private final Map<String, Integer> headerMap = new HashMap<>();  // 保存表头与列索引的映射

                        @Override
                        public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {
                            // 在这里获取并保存表头信息
                            for (Map.Entry<Integer, String> entry : headMap.entrySet()) {
                                headerMap.put(entry.getValue(), entry.getKey());
                            }
                        }

                        @Override
                        public void invoke(T data, AnalysisContext analysisContext) {
                            int rowIndex = analysisContext.readRowHolder().getRowIndex() + 1; // 获取当前行的行号，从1开始计数
                            try {
                                // 这里假设类 T 有一个名为 "column14Value" 的字段来存储第14列的值
                                if ("InvoiceInfo".equalsIgnoreCase(clazz.getSimpleName())) {

                                    Integer taxAmountIndex = headerMap.get("税额");
                                    Integer totalAmountIndex = headerMap.get("价税合计");
                                    ReadCellData cellTaxAmount = (ReadCellData) analysisContext.readRowHolder().getCellMap().get(taxAmountIndex);
                                    ReadCellData cellTotalAmount = (ReadCellData) analysisContext.readRowHolder().getCellMap().get(totalAmountIndex);

                                    BigDecimal valuecellTaxAmount = cellTaxAmount.getNumberValue().setScale(2, RoundingMode.HALF_UP);
                                    BigDecimal valueTotalAmount = cellTotalAmount.getNumberValue().setScale(2, RoundingMode.HALF_UP);

                                    Method setterTaxAmount = data.getClass().getMethod("setTaxAmount", Double.class);
                                    Method setterTotalAmount = data.getClass().getMethod("setTotalAmount", Double.class);
                                    setterTaxAmount.invoke(data, valuecellTaxAmount.doubleValue());
                                    setterTotalAmount.invoke(data, valueTotalAmount.doubleValue());

                                }

                                if ("WarehouseInfo".equalsIgnoreCase(clazz.getSimpleName())) {
                                    Integer tareWeightIndex = headerMap.get("购买方入库皮重");


                                    ReadCellData cellTareWeight = (ReadCellData) analysisContext.readRowHolder().getCellMap().get(tareWeightIndex);


                                    if (cellTareWeight != null && cellTareWeight.getNumberValue() != null) {
                                        BigDecimal valuecellTareWeight = cellTareWeight.getNumberValue().setScale(2, RoundingMode.HALF_UP);
                                        Method setterTaxAmount = data.getClass().getMethod("setTareWeight", Double.class);
                                        setterTaxAmount.invoke(data, valuecellTareWeight.doubleValue());
                                    }


                                    Integer amountIndex = headerMap.get("购买方询价金额");
                                    ReadCellData cellAmount = (ReadCellData) analysisContext.readRowHolder().getCellMap().get(amountIndex);
                                    if (cellAmount != null && cellAmount.getNumberValue() != null) {
                                        BigDecimal valuecellAmount = cellAmount.getNumberValue().setScale(2, RoundingMode.HALF_UP);
                                        Method setAmount = data.getClass().getMethod("setBuyerAmount", Double.class);
                                        setAmount.invoke(data, valuecellAmount.doubleValue());
                                    }


                                }


                                if ("ContractInfo".equalsIgnoreCase(clazz.getSimpleName())) {


                                    Integer sellerCompanyNameIndex = headerMap.get("销售方名称");

                                    ReadCellData cellsellerCompanyName = (ReadCellData) analysisContext.readRowHolder().getCellMap().get(sellerCompanyNameIndex);

                                    if (cellsellerCompanyName != null && cellsellerCompanyName.getStringValue() != null) {
                                        String valuecellsellerCompanyName = cellsellerCompanyName.getStringValue();
                                        Method setvalue = data.getClass().getMethod("setSellerCompanyName", String.class);
                                        setvalue.invoke(data, valuecellsellerCompanyName);
                                    }


                                    Integer tareWeightIndex = headerMap.get("购买方联系人");

                                    ReadCellData cellBuyerName = (ReadCellData) analysisContext.readRowHolder().getCellMap().get(tareWeightIndex);

                                    if (cellBuyerName != null && cellBuyerName.getStringValue() != null) {
                                        String valuecellBuyerName = cellBuyerName.getStringValue();
                                        Method setvalue = data.getClass().getMethod("setBuyerName", String.class);
                                        setvalue.invoke(data, valuecellBuyerName);
                                    }


                                }

                                if ("InvoiceDetails".equalsIgnoreCase(clazz.getSimpleName())) {



                                    Integer goodsNameIndex = headerMap.get("货物或应税劳务名称");
                                    ReadCellData goodsNameName = (ReadCellData) analysisContext.readRowHolder().getCellMap().get(goodsNameIndex);
                                    if (goodsNameName != null && goodsNameName.getStringValue() != null) {
                                        String value = goodsNameName.getStringValue();
                                        Method setvalue = data.getClass().getMethod("setGoodsName", String.class);
                                        setvalue.invoke(data, value);
                                    }



                                    Integer snoIndex = headerMap.get("序号");
                                    ReadCellData snoName = (ReadCellData) analysisContext.readRowHolder().getCellMap().get(snoIndex);
                                    if (snoName != null  ) {
                                        String valuesnoName =String.valueOf( snoName.getNumberValue() ) ;
                                        Method setvalue = data.getClass().getMethod("setSno", String.class);
                                        setvalue.invoke(data, valuesnoName);
                                    }


                                    Integer specificationIndex = headerMap.get("规格型号");
                                    ReadCellData specificationName = (ReadCellData) analysisContext.readRowHolder().getCellMap().get(specificationIndex);
                                    if (specificationName != null  ) {
                                        String valuespecificationName = specificationName.getStringValue();
                                        Method setvalue = data.getClass().getMethod("setSpecification", String.class);
                                        setvalue.invoke(data, valuespecificationName);
                                    }



                                    Integer goodsUnitPriceIndex = headerMap.get("单价");
                                    ReadCellData goodsUnitPriceName = (ReadCellData) analysisContext.readRowHolder().getCellMap().get(goodsUnitPriceIndex);
                                    if (goodsUnitPriceName != null && goodsUnitPriceName.getStringValue() != null) {
                                        String valueGoodsUnitPriceName = goodsUnitPriceName.getStringValue();
                                        Method setvalue = data.getClass().getMethod("setGoodsUnitPrice", String.class);
                                        setvalue.invoke(data, valueGoodsUnitPriceName);
                                    }

                                    Integer taxAmountIndex = headerMap.get("税额");
                                    ReadCellData taxAmountName = (ReadCellData) analysisContext.readRowHolder().getCellMap().get(taxAmountIndex);
                                    if (taxAmountName != null && taxAmountName.getNumberValue() != null) {
                                        String valueTaxAmountName = taxAmountName.getNumberValue().toPlainString();
                                        Method setvalue = data.getClass().getMethod("setTaxAmount", String.class);
                                        setvalue.invoke(data, valueTaxAmountName);
                                    }

                                    Integer taxRateIndex = headerMap.get("税率");
                                    ReadCellData taxRateName = (ReadCellData) analysisContext.readRowHolder().getCellMap().get(taxRateIndex);
                                    if (taxRateName != null && taxRateName.getStringValue() != null) {
                                        String valuetaxRateName = taxRateName.getStringValue();
                                        Method setvalue = data.getClass().getMethod("setTaxRate", String.class);
                                        valuetaxRateName = valuetaxRateName.replaceAll("%", "");
                                        setvalue.invoke(data, valuetaxRateName);
                                    }else {
                                        String valuetaxRateName =  String.valueOf( taxRateName.getNumberValue().doubleValue()*100)  ;
                                        Method setvalue = data.getClass().getMethod("setTaxRate", String.class);
                                        setvalue.invoke(data, valuetaxRateName);
                                    }


                                    Integer amountIndex = headerMap.get("金额");
                                    ReadCellData amountName = (ReadCellData) analysisContext.readRowHolder().getCellMap().get(amountIndex);
                                    if (amountName != null && amountName.getNumberValue() != null) {
                                        String valueAmountName = amountName.getNumberValue().toPlainString();
                                        Method setvalue = data.getClass().getMethod("setAmount", String.class);
                                        setvalue.invoke(data, valueAmountName);
                                    }


                                    Integer goodsQuantityIndex = headerMap.get("数量");
                                    ReadCellData goodsQuantityName = (ReadCellData) analysisContext.readRowHolder().getCellMap().get(goodsQuantityIndex);
                                    if (goodsQuantityName != null && goodsQuantityName.getNumberValue() != null) {
                                        String valuegoodsQuantityNameName = goodsQuantityName.getNumberValue().toPlainString();
                                        Method setvalue = data.getClass().getMethod("setGoodsQuantity", String.class);
                                        setvalue.invoke(data, valuegoodsQuantityNameName);
                                    }else {
                                        String valuegoodsQuantityNameName = goodsQuantityName.getStringValue();
                                        Method setvalue = data.getClass().getMethod("setGoodsQuantity", String.class);
                                        setvalue.invoke(data, valuegoodsQuantityNameName);
                                    }

                                    Integer orgCode = headerMap.get("所属公司编码");
                                    ReadCellData orgCodeName = (ReadCellData) analysisContext.readRowHolder().getCellMap().get(orgCode);
                                    if (orgCodeName != null && orgCodeName.getStringValue() != null) {
                                        String orgCodeNameV= orgCodeName.getStringValue();
                                        Method setvalue = data.getClass().getMethod("setOrgCode", String.class);
                                        setvalue.invoke(data, orgCodeNameV);
                                    }
                                }


                                // 在这里处理每一行 Excel 数据
                                dataList.add(data); // 将数据添加到集合中

                            } catch (ClassCastException e) {
                                e.printStackTrace();
                                handleException(analysisContext, e, "第" + rowIndex + "行数据 有问题 ");
                            } catch (Exception e) {
                                e.printStackTrace();
                                handleException(analysisContext, e, "第" + rowIndex + "    行数据 有问题 =====================");
                            }
                        }

                        @Override
                        public void doAfterAllAnalysed(AnalysisContext analysisContext) {
                            // 所有数据处理完毕后的操作
                        }

                        private void handleException(AnalysisContext context, Exception e, String message) {
                            int rowIndex = context.readRowHolder().getRowIndex() + 1; // 获取行号
                            Map<Integer, Cell> cellDataMap = context.readRowHolder().getCellMap();
                            for (Map.Entry<Integer, Cell> entry : cellDataMap.entrySet()) {
                                int columnIndex = entry.getKey() + 1; // 获取列号，从1开始计数
                                entry.getValue();
                                String columnName = getColumnHeader(context, columnIndex);
                                System.err.println(message + rowIndex + ", column " + columnIndex + " (" + columnName + "): "
                                        + e.getMessage());
                            }
                            e.printStackTrace();
                            throw new RuntimeException("Error processing row " + rowIndex + ": " + e.getMessage(), e);
                        }

                        private String getColumnHeader(AnalysisContext context, int columnIndex) {

                            return columnIndex + "报错";
                        }
                    }
            ).build();
            excelReader.read(readSheet);
            return dataList;
        } finally {
            // 关闭 ExcelReader
            excelReader.finish();
        }
    }
}
